﻿using BZ.Core.TaskExt;
using BZ.Logger;
using BZVision;
using CBUMachineDataManage.MachineData;
using MvCamCtrl.NET;
using NDK.AcqDevice.Gocator;
using NDK.AcqDevice.HikVision;
using NDK.Frm;
using NDK.Laser.SSZN;
using NDK.LocalUtils.Yield;
using NDK.Module.DAL;
using NDK.Module.Model;
using NDK.Module.StationLogic;
using NDK.Motion.BLL;
using NDK.Motion.MachineManager;
using NDK.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using VisionPlatform;
using static NDK.Module.BLL.Configuration;

namespace NDK.Module.BLL
{
    public static class SysInit
    {
        /// <summary>
        /// 初始化框架，一般在程序启动时调用一次
        /// </summary>
        /// <param name="showStartWindow">指示是否显示程序启动时的欢迎窗体</param>
        public static void Init ()
        {
            try
            {
                //加载中英文切换字典，可写到配置文件，这里写死了
                Common.languageDic.Add("Function", "功能");
                Common.languageDic.Add("StartVelocity", "初速度");
                Common.languageDic.Add("MoveVelocity", "运行速度");
                Common.languageDic.Add("AccTime", "加速时间");
                Common.languageDic.Add("DecTime", "减速时间");
                Common.languageDic.Add("AxisPriority", "优先级");
                Common.languageDic.Add("Project", "项目");
                Common.languageDic.Add("Description", "说明");

                if(File.Exists($"{Common.pointCheckPath}\\Mes.json"))
                {
                    Common.SwMes = JsonConvert.DeserializeObject<SunWayMes>(File.ReadAllText($"{Common.pointCheckPath}\\Mes.json"));
                }

                Dlg_SelectProject selectProjectDialog = new Dlg_SelectProject();
                if(selectProjectDialog.ShowDialog(Frm_Home.Instance) == DialogResult.OK)
                {
                    Frm_Welcome.Instance.Show();
                    Frm_InitItemStatu.Instance.UpdateStep(1, language == Language.English ? "LoadingProduct Forms" : "加载窗体");
                    MachineDataManager.LoadFromFile();
                    PublicMethod.LoadProTypeMeasureItemEnableConfig();
                    PublicMethod.LoadProTypeParam();
                    Frm_Main frm = null;
                    try
                    {
                        frm = Frm_Main.Instance;          //这一句看似没用，实则有用，因为在这里加这一行就会实例化主窗体，不然主窗体就会在后台线程中被实例化，那就会有问题
                        var frm_setting = Frm_Setting.Instance;
                        var alarmFrom = Frm_Alarm2.Instance;

                        var frm_Login = Frm_Login.Instance;
                        var frm_Statistics = Frm_Statistics.Instance;
                    }
                    catch(Exception ex)
                    {
                        MessageBox.Show($"未处理的异常：{ex.StackTrace}");
                    }
                    Frm_InitItemStatu.Instance.UpdateStep(5, language == Language.English ? "Forms Load OK" : "窗体加载成功！", true);
                    TaskManager.Run(() =>
                    {
                        MachineInit();
                    });
                    while(LoadingProduct1 && !Common.IsOfflineMode)
                    {
                        Thread.Sleep(5);
                        Application.DoEvents();
                    }
                    Frm_Welcome.Instance.Close();
                    frm.ShowDialog();
                }
            }
            catch(Exception ex)
            {
                try
                {
                    Frm_Welcome.Instance.ShowDialog();
                }
                catch(Exception es)
                {
                    if(ex.Message.Contains("DevComponents.DotNetBar2"))
                    {
                        DialogResult result = MessageBox.Show(language == Language.English ? "An image with the same name already exists, is it overwritten?" : "启动失败，本机未安装此程序所依赖的组件，是否立即安装？", language == Language.English ? "Tip:" : "提示：", MessageBoxButtons.YesNo);
                        if(result == DialogResult.Yes)
                        {
                            Process.Start(Application.StartupPath + "\\Installs\\DotNetBar for Windows Forms 12.0.0.1.exe");
                        }
                    }
                    else
                    {
                    }
                }
            }
        }
        /// <summary>
        /// 表示程序启动时是否初始化成功
        /// </summary>
        internal static bool initSucceed = true;
        /// <summary>
        /// 是否处于前台生产状态，分前台生产状态和后台调试状态
        /// </summary>
        internal static bool productionMode = true;
        /// <summary>
        /// 记录旧的时间
        /// </summary>
        internal static DateTime oldTime = DateTime.Now;
        /// <summary>
        /// 总生产时间
        /// </summary>
        internal static TimeSpan runTime;
        /// <summary>
        /// 总待机时间
        /// </summary>
        internal static TimeSpan waitTime;
        /// <summary>
        /// 总报警时间
        /// </summary>
        internal static TimeSpan alarmTime;
        /// <summary>
        /// 资源锁
        /// </summary>
        internal static object lock_resources = new object();
        /// <summary>
        /// 是否已经显示
        /// </summary>
        internal static bool hasShown = false;
        internal static bool LoadingProduct1 = true;
        internal static List<bool> isMachineInit = new List<bool>();



        /// <summary>
        /// 初始化
        /// </summary>
        //[Interceptor]
        public static void MachineInit ()
        {
            try
            {
                bool isok = false;
                #region 创建相机参数文件夹
                if(!Directory.Exists(Common.PathConfig))
                    Directory.CreateDirectory(Common.PathConfig);
                if(!Directory.Exists(Common.PathLog))
                    Directory.CreateDirectory(Common.PathLog);
                #endregion

                #region 读取软件版本
                Frm_InitItemStatu.Instance.UpdateStep(6, language == Language.English ? "Open SoftWare Version Info" : $"读取软件版本信息");
                try
                {
                    isok = true;
                    string path = Application.StartupPath + @"\Config\SoftwareVersionInfo.csv";
                    DataTable dt = FileUtils.OpenCSV(path);
                    string LocalVersion = dt.Rows[dt.Rows.Count - 1][0].ToString();
                    if(Common.currentVersion != LocalVersion)
                    {
                        Common.AppendUiLog.Log("本地配置文件版本与软件版本不一致");
                    }
                    else
                    {
                        Frm_Main.Instance.Text += LocalVersion;
                    }
                }
                catch(Exception)
                {
                    isok = false;
                }
                isMachineInit.Add(isok);
                Frm_InitItemStatu.Instance.UpdateStep(10, language == Language.English ? $"Open SoftWare Version Info {(isok ? "OK" : "Fail")}" : $"读取软件版本信息{(isok ? "成功" : "失败")}", isok);
                #endregion

                #region 读取交接班时间+读取产量统计信息
                Frm_InitItemStatu.Instance.UpdateStep(11, "读取产能配置");
                try
                {
                    isok = Yield.Instance.ReadYield();
                }
                catch(Exception)
                {
                    isok = false;
                }
                isMachineInit.Add(isok);
                Frm_InitItemStatu.Instance.UpdateStep(15, $"读取产能配置{(isok ? "成功" : "失败")}", isok);
                #endregion

                if(!Common.IsOfflineMode)
                {
                    #region 更新系统参数
                    Frm_InitItemStatu.Instance.UpdateStep(16, "更新系统参数");
                    try
                    {
                        isok = true;
                        PublicMethod.UpdateRuningData();   //还是需要挑选哪些变量要更新
                        AlarmInfoServices alarmInfoServices = new AlarmInfoServices();
                        DateTime dt = DateTime.Now.AddDays(-Common.IP_报警信息保留时间);//删除N天前的报警信息
                        alarmInfoServices.DeleteBeforeTime(dt);
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(20, $"更新系统参数{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region 加载视觉框架
                    Frm_InitItemStatu.Instance.UpdateStep(21, "加载视觉框架");
                    try
                    {
                        isok = true;
                        Vision.Intial();
                        //VisionManager.Event.LogDebug += Event_LogDebug;
                        //VisionManager.Event.LogError += Event_LogError;
                        //VisionManager.Event.LogFatal += Event_LogFatal;
                        //VisionManager.Event.LogInfo += Event_LogInfo;
                        //VisionManager.Event.LogWarn += Event_LogWarn;
                        //VisionManager.Event.LogModify += Event_LogModify;
                        VisionManager.Event.GetAuthority += Event_GetAuthority;

                        VisionManager.Engine eng = null;
                        eng = new VisionManager.Engine("InitialVariable");
                        eng.ActionFun();
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(25, $"加载视觉框架{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region 初始化海康相机
                    Frm_InitItemStatu.Instance.UpdateStep(26, "初始化海康相机");
                    try
                    {
                        Common.HikVisionList = new List<MvCameraController>();
                        MyCamera.MV_CC_DEVICE_INFO_LIST DeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
                        MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref DeviceList);
                        IntPtr[] Ptrs = DeviceList.pDeviceInfo;
                        // TOM修改
                        if(Ptrs[3] != IntPtr.Zero)
                        {
                            isok = true;
                            //判断相机个数 TOM
                            for(int i = 0; i < 4; i++)
                            {
                                Common.HikVisionList.Add(new MvCameraController(Ptrs[i]));
                                if(!Common.HikVisionList[i].Connect())
                                {
                                    isok = false;
                                    break;
                                }

                            }
                        }
                        else
                        {
                            isok = false;
                        }
                    }
                    catch(Exception)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(30, $"初始化海康相机{(isok ? "成功" : "失败")}", isok);
                    #endregion  

                    #region 加载算法Slp
                    Frm_InitItemStatu.Instance.UpdateStep(31, "加载算法Slp");
                    try
                    {
                        isok = PublicMethod.LoadSlp(Common.CurProType, Common.ProjectName);
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(35, $"加载算法Slp{(isok ? "成功" : "失败")}", isok);
                    #endregion    

                    #region 连接MES上传系统
                    MachineDataCollectRequest request = new MachineDataCollectRequest();


                    #endregion

                    //#region 指纹仪初始化
                    //Frm_InitItemStatu.Instance.UpdateStep(36, language == Language.English ? "Initial FingerPrint Device" : "初始化指纹仪");
                    //try
                    //{
                    //    isok = Common.isFingerPrintInitialed = Frm_Login.Instance.InitFPDevice();
                    //}
                    //catch (Exception)
                    //{
                    //    isok = Common.isFingerPrintInitialed = false;
                    //}
                    //Frm_InitItemStatu.Instance.UpdateStep(40, language == Language.English ? $"Initial FingerPrint Device {(isok ? "OK" : "Fail")}" : $"初始化指纹仪{(isok ? "成功" : "失败")}", isok);
                    //#endregion  

                    #region 光源初始化
                    Frm_InitItemStatu.Instance.UpdateStep(41, "初始化光源控制器");
                    try
                    {
                        var allOK = new List<bool>();
                        foreach(var lightController in MachineDataManager.Instance.LightControllerList)
                        {
                            lightController.Disconnect();
                            if(lightController.IsConnect == false)
                            {
                                if(lightController.Connect())
                                {
                                    allOK.Add(true);
                                    lightController.CloseAllLight();
                                }
                                else
                                {
                                    allOK.Add(false);
                                }
                            }
                        }
                        isok = allOK.FindAll(x => x == false).Count == 0;
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(45, $"初始化光源控制器{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region 扫码枪初始化
                    Frm_InitItemStatu.Instance.UpdateStep(46, "初始化扫码枪");
                    try
                    {
                        Common.ScanReader.ReaderIP = "192.168.100.100";
                        isok = Common.ScanReader.ConnectReader();
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(50, $"初始化扫码枪{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region PPG初始化
                    Frm_InitItemStatu.Instance.UpdateStep(51, "初始化PPG");
                    try
                    {
                        if(Machine.PPG.Init(Common.SP_PPGIP1, 64000))
                        {
                            isok = true;
                        }
                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(55, $"初始化PPG{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region 激光初始化
                    Frm_InitItemStatu.Instance.UpdateStep(56, "初始化激光");
                    string msg = string.Empty;
                    try
                    {

                        Common.Lmi_短边前激光 = new GocatorController();
                        Common.Lmi_短边后激光 = new GocatorController();
                        Common.Lmi_长边左激光 = new GocatorController();
                        Common.Lmi_长边右激光 = new GocatorController();
                        Common.SSZN_上激光 = new SRController();
                        Common.SSZN_侧激光 = new SRController();
                        Common.SSZN_下激光 = new SRController();
                        Common.SSZN_上激光.currentDeviceId = 0;
                        Common.SSZN_侧激光.currentDeviceId = 1; 
                        Common.SSZN_下激光.currentDeviceId = 2;
                        if(!Common.Lmi_短边前激光.Connect(Common.SP_工位5_LMI短边前激光IP))
                        {
                            msg += "Lmi_短边前激光,连接失败！";
                        }
                        if(!Common.Lmi_短边后激光.Connect(Common.SP_工位5_LMI短边后激光IP))
                        {
                            msg += "Lmi_短边后激光,连接失败！";
                        }
                        if(!Common.Lmi_长边左激光.Connect(Common.SP_工位6_长边左激光IP))
                        {
                            msg += "Lmi_长边左激光,连接失败！";
                        }
                        if(!Common.Lmi_长边右激光.Connect(Common.SP_工位6_长边右激光IP))
                        {
                            msg += "Lmi_长边右激光,连接失败！";
                        }

                        if(!Common.SSZN_上激光.Connect(Common.SP_工位3_深视上激光IP))
                        {
                            msg += "Lmi_深视上激光,连接失败！";
                        }
                        if(!Common.SSZN_侧激光.Connect(Common.SP_工位7_深视侧激光IP))
                        {
                            msg += "Lmi_深视侧激光,连接失败！";
                        }
                        if(!Common.SSZN_下激光.Connect(Common.SP_深视下激光IP))
                        {
                            msg += "Lmi_深视下激光,连接失败！";
                        }
                        else if(!string.IsNullOrEmpty(msg))
                        {
                            MessageBox.Show($"激光连接失败\r\n {msg}", "提示",
                                             MessageBoxButtons.OK,
                                             MessageBoxIcon.Information,
                                             MessageBoxDefaultButton.Button1,
                                             MessageBoxOptions.DefaultDesktopOnly);
                        }
                        else
                        {
                            isok = true;
                        }

                    }
                    catch(Exception ex)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(60, $"初始化激光{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    #region 连接PLC
                    Frm_InitItemStatu.Instance.UpdateStep(61, "初始化PLC");
                    try
                    {
                        if(!HslCommunication.Authorization.SetAuthorizationCode("12a99167-05ff-4c89-936f-93d42033f882"))
                        {
                            Common.AppendUiLog.Log("激活失败", LogType.Error);
                        }
                        isok = Common.OmronPLC.ConnectServer().IsSuccess;
                        Common.opreateResult_Isconnect.IsSuccess = isok;
                    }
                    catch(Exception)
                    {
                        isok = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(66, $"初始化PLC{(isok ? "成功" : "失败")}", isok);
                    #endregion //   TOM修改

                    #region 运动板卡初始化
                    try
                    {
                        Frm_InitItemStatu.Instance.UpdateStep(86, "初始化运动板卡");
                        if(MachineDataManager.Instance.CardList.Count > 0)
                        {
                            //如果在界面手动初始化了，这里就不需要再初始化了
                            foreach(var card in MachineDataManager.Instance.CardList)
                            {
                                //运动卡初始化
                                if(card.Initialized == false)
                                {
                                    try
                                    {
                                        isok = card.CardInit(0);
                                    }
                                    catch(Exception ex)
                                    {
                                        isok = LoadingProduct1 = false;
                                        return;
                                    }
                                }
                                else
                                {
                                    isok = LoadingProduct1 = false;
                                    return;
                                }
                            }
                            Machine.MachineResourceInit();
                            MotionControl.PropertyChanged += MotionControl_PropertyChanged;
                            Frm_InitItemStatu.Instance.UpdateStep(90, $"运动卡初始化{(isok ? "成功" : "失败")}", isok);

                            //报警清除
                            isok = true;
                            foreach(var axis in MachineDataManager.Instance.AxisList)
                            {
                                if(!axis.ClearAlarm())
                                {
                                    isok = false;
                                    isMachineInit.Add(false);
                                    Common.AppendUiLog.Log($"运动板卡清除轴[{axis.AxisID}]报警失败", LogType.Error);
                                }
                            }
                            Frm_InitItemStatu.Instance.UpdateStep(95, $"运动板卡清除报警{(isok ? "成功" : "失败")}", isok);

                            isok = Common.isCardInitialed = MotionControl.AllAxisServoON().bRtn;
                        }
                    }
                    catch(Exception ex)
                    {
                        isok = Common.isCardInitialed = false;
                    }
                    isMachineInit.Add(isok);
                    Frm_InitItemStatu.Instance.UpdateStep(100, $"初始化运动板卡参数{(isok ? "成功" : "失败")}", isok);
                    #endregion

                    //最终判定
                    Common.IsIniSucess = isMachineInit.FindAll(x => x == false).Count == 0;
                }
            }
            catch(Exception ex)
            {
                Common.IsIniSucess = false;
            }
            Frm_InitItemStatu.Instance.UpdateStep(100, $"设备硬件初始化{(Common.IsIniSucess ? "成功" : "失败")}", Common.IsIniSucess);
            LoadingProduct1 = false;
        }

        public static Authority Event_GetAuthority ()
        {
            switch(Common.Authority)
            {
                case "Operator":
                case "BZ":
                case "EN":
                case "Battery QM":
                //return Authority.ProdocutOp;
                case "Apple":
                    return VisionPlatform.Authority.ProdouctEng;
                default:
                    return VisionPlatform.Authority.ProdouctEng;//暂时有算法权限
            }
        }

        private static void MotionControl_PropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Common.AppendUiLog.Log(e.PropertyName, LogType.Alert);
        }


        // Any attribute which provides OnEntry/OnExit/OnException with proper args
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
        public class InterceptorAttribute : Attribute
        {
            // instance, method and args can be captured here and stored in attribute instance fields
            // for future usage in OnEntry/OnExit/OnException
            public void Init (object instance, MethodBase method, object[] args)
            {
                Console.WriteLine(string.Format("Init: {0} [{1}]", method.DeclaringType.FullName + "." + method.Name, args.Length));
            }

            public void OnEntry ()
            {
                Console.WriteLine("OnEntry");
            }

            public void OnExit ()
            {
                Console.WriteLine("OnExit");
            }

            public void OnException (Exception exception)
            {
                MessageBox.Show(string.Format("OnException: {0}: {1}", exception.GetType(), exception.Message));
            }
        }

    }
}
